import tkinter as tk
from tkinter import ttk, messagebox, scrolledtext
import socket
import threading
import sys
import os
from datetime import datetime
from configparser import ConfigParser

class IPv6toIPv4Forwarder:
    def __init__(self, root):
        self.root = root
        self.root.title("IPLink")
        self.root.geometry("485x640")
        self.root.resizable(False, False)
        self.config = ConfigParser()
        self.config.read('_internal/config.ini', encoding='utf-8')

        # 运行状态
        self.is_running = False
        self.sockets = []
        self.threads = []
        
        # 创建界面
        self.create_widgets()
        
    def create_widgets(self):
        # 主框架
        main_frame = ttk.Frame(self.root, padding="10")
        main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # 标题
        title_label = ttk.Label(main_frame, text="IPv4至IPv6双向socket转发", font=("Arial", 16, "bold"))
        title_label.grid(row=0, column=0, columnspan=2, pady=(0, 15))
        
        # 模式选择
        # 默认模式读取配置文件
        try:
            mode_vale = self.config.get('config', 'mode')
        except:
            mode_vale = 'client'
        if mode_vale not in ['client', 'server']:
            mode_vale = 'client'

        mode_frame = ttk.LabelFrame(main_frame, text="运行模式", padding="10")
        mode_frame.grid(row=1, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=(0, 10))
        self.mode_var = tk.StringVar(value=mode_vale)
        ttk.Radiobutton(mode_frame, text="客户端模式", variable=self.mode_var, value="client", command=self.update_ui).grid(row=0, column=0, sticky=tk.W)
        ttk.Radiobutton(mode_frame, text="服务端模式", variable=self.mode_var, value="server", command=self.update_ui).grid(row=0, column=1, sticky=tk.W)
        
        # 配置区域
        config_frame = ttk.LabelFrame(main_frame, text="转发配置", padding="10")
        config_frame.grid(row=2, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=(0, 10))
        
        tempn = 0 # 用于调整布局
        # 本地IPv4地址
        try:
            local_ipv4_value = self.config.get('config', 'local_ipv4')
        except:
            local_ipv4_value = "127.0.0.1"

        ttk.Label(config_frame, text="本地IPv4地址:").grid(row=tempn, column=0, sticky=tk.W, pady=2)
        self.local_ipv4_var = tk.StringVar(value=local_ipv4_value)
        ttk.Entry(config_frame, textvariable=self.local_ipv4_var, width=20).grid(row=0, column=1, sticky=(tk.W, tk.E), pady=2, padx=(5, 0))
        tempn = tempn + 1

        # 游戏端口
        try:
            game_port_value = self.config.get('config', 'game_port')
        except:
            game_port_value = "25565"

        ttk.Label(config_frame, text="游戏端口:").grid(row=tempn, column=0, sticky=tk.W, pady=2)
        self.game_port_var = tk.StringVar(value=game_port_value)
        ttk.Entry(config_frame, textvariable=self.game_port_var, width=20).grid(row=1, column=1, sticky=(tk.W, tk.E), pady=2, padx=(5, 0))
        tempn = tempn + 1
        
        # 对端IPv6地址
        try:
            remote_ipv6_value = self.config.get('config', 'remote_ipv6')
        except:
            remote_ipv6_value = "" 

        ttk.Label(config_frame, text="对端IPv6地址:").grid(row=tempn, column=0, sticky=tk.W, pady=2)
        self.remote_ipv6_var = tk.StringVar(value=remote_ipv6_value)
        self.remote_ipv6_entry = ttk.Entry(config_frame, textvariable=self.remote_ipv6_var, width=40)
        self.remote_ipv6_entry.grid(row=tempn, column=1, sticky=(tk.W, tk.E), pady=2, padx=(5, 0))
        tempn = tempn + 1
        
        # 对端游戏端口
        try:
            remote_port_value = self.config.get('config', 'remote_port')
        except:
            remote_port_value = "25566"

        ttk.Label(config_frame, text="对端游戏端口:").grid(row=tempn, column=0, sticky=tk.W, pady=2)
        self.remote_port_var = tk.StringVar(value=remote_port_value) #默认与服务器转发端口相同
        self.remote_port_entry = ttk.Entry(config_frame, textvariable=self.remote_port_var, width=20)
        self.remote_port_entry.grid(row=tempn, column=1, sticky=(tk.W, tk.E), pady=2, padx=(5, 0))
        tempn = tempn + 1
        
        # 服务端IPv6地址（仅服务端模式显示）
        try:
            server_ipv6_value = self.config.get('config', 'server_ipv6')
        except:
            server_ipv6_value = "" # 表示未设置,将自动获取

        ttk.Label(config_frame, text="服务端IPv6地址:").grid(row=tempn, column=0, sticky=tk.W, pady=2)
        self.server_ipv6_var = tk.StringVar(value=server_ipv6_value)
        self.server_ipv6_entry = ttk.Entry(config_frame, textvariable=self.server_ipv6_var, width=40)
        self.server_ipv6_entry.grid(row=tempn, column=1, sticky=(tk.W, tk.E), pady=2, padx=(5, 0))
        tempn = tempn + 1

        # 服务端IPv6端口（新增）
        try:
            server_port_value = self.config.get('config', 'server_port')
        except:
            server_port_value = "25566"  # 默认端口

        ttk.Label(config_frame, text="服务端IPv6端口:").grid(row=tempn, column=0, sticky=tk.W, pady=2)
        self.server_port_var = tk.StringVar(value=server_port_value)  # 默认使用不同端口
        self.server_port_entry = ttk.Entry(config_frame, textvariable=self.server_port_var, width=20)
        self.server_port_entry.grid(row=tempn, column=1, sticky=(tk.W, tk.E), pady=2, padx=(5, 0))
        tempn = tempn + 1
        
        # 协议选择
        try:
            protocol_value = self.config.get('config', 'protocol')
        except:
            protocol_value = "TCP"
        if protocol_value not in ['UDP', 'TCP']:
            protocol_value = "TCP"

        ttk.Label(config_frame, text="协议:").grid(row=tempn, column=0, sticky=tk.W, pady=2)
        self.protocol_var = tk.StringVar(value=protocol_value)
        protocol_combo = ttk.Combobox(config_frame, textvariable=self.protocol_var, state="readonly", width=17)
        protocol_combo['values'] = ('UDP', 'TCP')
        protocol_combo.grid(row=tempn, column=1, sticky=tk.W, pady=2, padx=(5, 0))
        tempn = tempn + 1
        
        # 按钮区域
        button_frame = ttk.Frame(main_frame)
        button_frame.grid(row=3, column=0, columnspan=4, pady=(0, 10))
        
        self.start_button = ttk.Button(button_frame, text="启动转发", command=self.start_forwarding)
        self.start_button.pack(side=tk.LEFT, padx=(0, 10))
        
        self.stop_button = ttk.Button(button_frame, text="停止转发", command=self.stop_forwarding, state=tk.DISABLED)
        self.stop_button.pack(side=tk.LEFT)
        
        self.save_button = ttk.Button(button_frame, text="保存配置", command=self.save_config)
        self.save_button.pack(side=tk.LEFT, padx=(10, 0))

        self.auto_button = ttk.Button(button_frame, text="自动获取IPv6", command=self.auto_get_ipv6)
        self.auto_button.pack(side=tk.LEFT, padx=(10, 0))
        if self.mode_var.get() == "server":
            self.auto_button.config(state=tk.NORMAL)
        else:
            self.auto_button.config(state=tk.DISABLED)

        # 日志区域
        log_frame = ttk.LabelFrame(main_frame, text="日志", padding="10")
        log_frame.grid(row=4, column=0, columnspan=2, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        self.log_text = scrolledtext.ScrolledText(log_frame, height=12, width=60) # 目前最大，决定了窗口最小宽度
        self.log_text.pack(fill=tk.BOTH, expand=True)
        
        # 状态栏
        self.status_var = tk.StringVar(value="就绪") # 也会影响窗口宽度
        status_bar = ttk.Label(main_frame, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W)
        status_bar.grid(row=5, column=0, columnspan=2, sticky=(tk.W, tk.E))
        
        # 配置网格权重
        main_frame.columnconfigure(0, weight=1)
        main_frame.rowconfigure(4, weight=1)
        config_frame.columnconfigure(1, weight=1)
        log_frame.columnconfigure(0, weight=1)
        log_frame.rowconfigure(0, weight=1)
        
        # 绑定关闭事件
        self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
        
        # 初始化UI状态
        self.update_ui()
        
    def update_ui(self):
        """根据模式更新UI"""
        if self.mode_var.get() == "server":
            # 服务端模式
            self.remote_ipv6_entry.config(state='disabled')
            self.remote_port_entry.config(state='disabled')
            self.server_ipv6_entry.config(state='normal')
            self.server_port_entry.config(state='normal')
            self.auto_button.config(state=tk.NORMAL)
            # 尝试自动获取IPv6地址
            if self.server_ipv6_var.get() == "":
                try:
                    s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
                    s.connect(("2400:3200::1", 80))  # ali IPv6 DNS
                    ipv6 = s.getsockname()[0]
                    self.server_ipv6_var.set(ipv6)
                    s.close()
                except:
                    self.server_ipv6_var.set("::1")  # 回环地址作为备选
                    self.log_message("DNS解析失败,请检查是否支持ipv6,或尝试手动配置ipv6地址") # 无法获取IPv6地址时不做处理
        else:
            # 客户端模式
            self.remote_ipv6_entry.config(state='normal')
            self.remote_port_entry.config(state='normal')
            self.server_ipv6_entry.config(state='disabled')
            self.server_port_entry.config(state='disabled')
            self.auto_button.config(state=tk.DISABLED)
            try:
                s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
                s.connect(("2400:3200::1", 80))  # ali IPv6 DNS
                ipv6 = s.getsockname()[0]
                s.close()
                if self.server_ipv6_var.get() == ipv6:
                    self.server_ipv6_var.set("")  # 如果是自动获取的地址，则清空
            except:
                self.log_message("DNS解析失败,请检查是否支持ipv6,或尝试手动配置ipv6地址")  # 无法获取IPv6地址时不做处理

            # self.server_ipv6_var.set("") # 清空服务端IPv6地址,还是保留上次输入的好
        
    def log_message(self, message):
        """添加消息到日志"""
        timestamp = datetime.now().strftime("%H:%M:%S")
        formatted_message = f"[{timestamp}] {message}\n"
        self.log_text.insert(tk.END, formatted_message)
        self.log_text.see(tk.END)
        self.root.update_idletasks()
        
    def start_forwarding(self):
        """启动转发"""
        try:
            # 获取配置参数
            local_ipv4 = self.local_ipv4_var.get()
            game_port = int(self.game_port_var.get())
            protocol = self.protocol_var.get().lower()
            mode = self.mode_var.get()
            
            # 验证参数
            if mode == "client":
                remote_ipv6 = self.remote_ipv6_var.get()
                remote_port = int(self.remote_port_var.get())
                if not remote_ipv6:
                    messagebox.showerror("错误", "请输入对端IPv6地址")
                    return
            else:  # server mode
                server_ipv6 = self.server_ipv6_var.get()
                server_port = int(self.server_port_var.get())
                if not server_ipv6:
                    messagebox.showerror("错误", "请输入服务端IPv6地址")
                    return
                if server_port == game_port:
                    if not messagebox.askyesno("警告", "服务端IPv6端口与游戏端口相同，这可能导致冲突。是否继续？"):
                        return
                
            # 创建转发器
            self.is_running = True
            
            # 根据协议创建socket
            if protocol == "udp":
                sock_type = socket.SOCK_DGRAM
            else:
                sock_type = socket.SOCK_STREAM
                
            # 创建IPv4监听socket
            if mode == "server" and protocol == "tcp":
                ipv4_sock = None  # 不需要IPv4监听socket
            else:
                # 创建IPv4监听socket
                ipv4_sock = socket.socket(socket.AF_INET, sock_type)
                ipv4_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
                ipv4_sock.bind((local_ipv4, game_port))
                
                if protocol == "tcp":
                    ipv4_sock.listen(5)
                
            # 创建IPv6 socket
            ipv6_sock = socket.socket(socket.AF_INET6, sock_type)
            ipv6_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            
            self.sockets.extend([ipv4_sock, ipv6_sock])
            
            # 启动转发线程
            if protocol == "udp":
                if mode == "client":
                    thread = threading.Thread(target=self.udp_forwarder_client, 
                                             args=(ipv4_sock, ipv6_sock, remote_ipv6, remote_port))
                else:
                    thread = threading.Thread(target=self.udp_forwarder_server, 
                                             args=(ipv4_sock, ipv6_sock, server_ipv6, server_port, game_port))
            else:
                if mode == "client":
                    thread = threading.Thread(target=self.tcp_forwarder_client, 
                                             args=(ipv4_sock, ipv6_sock, remote_ipv6, remote_port))
                else:
                    thread = threading.Thread(target=self.tcp_forwarder_server, 
                                             args=(ipv4_sock, ipv6_sock, server_ipv6, server_port, game_port))
            
            thread.daemon = True
            thread.start()
            self.threads.append(thread)
            
            # 更新UI状态
            self.start_button.config(state=tk.DISABLED)
            self.stop_button.config(state=tk.NORMAL)
            
            if mode == "client":
                status_text = f" {local_ipv4}:{game_port} -> [{remote_ipv6}]:{remote_port} ({protocol.upper()})"
                self.log_message(f"启动转发: {local_ipv4}:{game_port} -> [{remote_ipv6}]:{remote_port} ({protocol.upper()})")
            else:
                status_text = f" [{server_ipv6}]:{server_port} <- {local_ipv4}:{game_port} ({protocol.upper()})"
                self.log_message(f"启动服务端: [{server_ipv6}]:{server_port} <- {local_ipv4}:{game_port} ({protocol.upper()})")
                
            self.status_var.set(status_text)
            
        except Exception as e:
            self.log_message(f"启动失败: {str(e)}")
            messagebox.showerror("错误", f"启动失败: {str(e)}")
            self.stop_forwarding()
            
    def stop_forwarding(self):
        """停止转发"""
        self.is_running = False
        
        # 关闭所有socket
        for sock in self.sockets:
            try:
                sock.close()
            except:
                pass
                
        self.sockets = []
        self.threads = []
        
        # 更新UI状态
        self.start_button.config(state=tk.NORMAL)
        self.stop_button.config(state=tk.DISABLED)
        self.status_var.set("已停止")
        self.log_message("转发已停止")
        
    def udp_forwarder_client(self, ipv4_sock, ipv6_sock, remote_ipv6, remote_port):
        """UDP客户端转发器"""
        self.log_message("UDP客户端转发器已启动")
        
        # 设置超时以便检查运行状态
        ipv4_sock.settimeout(1.0)
        ipv6_sock.settimeout(1.0)
        
        while self.is_running:
            try:
                # 接收IPv4数据
                data, addr = ipv4_sock.recvfrom(4096)
                if data:
                    self.log_message(f"从 {addr} 收到 {len(data)} 字节数据，转发到 [{remote_ipv6}]:{remote_port}")
                    # 转发到IPv6
                    ipv6_sock.sendto(data, (remote_ipv6, remote_port, 0, 0))
                    
                    # 接收IPv6响应
                    try:
                        response, resp_addr = ipv6_sock.recvfrom(4096)
                        if response:
                            self.log_message(f"从 [{resp_addr[0]}]:{resp_addr[1]} 收到 {len(response)} 字节响应，转发到 {addr}")
                            ipv4_sock.sendto(response, addr)
                    except socket.timeout:
                        pass
                    
            except socket.timeout:
                continue
            except socket.error as e:
                if self.is_running:
                    self.log_message(f"UDP错误: {str(e)}")
                break
                
        self.log_message("UDP客户端转发器已停止")
        
    def udp_forwarder_server(self, ipv4_sock, ipv6_sock, server_ipv6, server_port, game_port):
        """UDP服务端转发器 - 使用指定端口"""
        self.log_message(f"UDP服务端转发器已启动，监听端口 {server_port}")
        
        # 绑定IPv6 socket到服务端地址和指定端口
        ipv6_sock.bind((server_ipv6, server_port))
        
        # 设置超时以便检查运行状态
        ipv4_sock.settimeout(1.0)
        ipv6_sock.settimeout(1.0)
        
        while self.is_running:
            try:
                # 接收IPv6数据
                data, addr = ipv6_sock.recvfrom(4096)
                if data:
                    self.log_message(f"从 [{addr[0]}]:{addr[1]} 收到 {len(data)} 字节数据，转发到本地游戏")
                    # 转发到IPv4游戏端口
                    ipv4_sock.sendto(data, (self.local_ipv4_var.get(), game_port))
                    
                    # 接收IPv4响应
                    try:
                        response, resp_addr = ipv4_sock.recvfrom(4096)
                        if response:
                            self.log_message(f"从本地游戏收到 {len(response)} 字节响应，转发到 [{addr[0]}]:{addr[1]}")
                            ipv6_sock.sendto(response, addr)
                    except socket.timeout:
                        pass
                    
            except socket.timeout:
                continue
            except socket.error as e:
                if self.is_running:
                    self.log_message(f"UDP错误: {str(e)}")
                break
                
        self.log_message("UDP服务端转发器已停止")
        
    def tcp_forwarder_client(self, ipv4_sock, ipv6_sock, remote_ipv6, remote_port):
        """TCP客户端转发器"""
        self.log_message("TCP客户端转发器已启动")
        
        try:
            # 连接到远程IPv6
            ipv6_sock.connect((remote_ipv6, remote_port, 0, 0))
            self.log_message(f"已连接到 [{remote_ipv6}]:{remote_port}")
            
            while self.is_running:
                # 接受IPv4连接
                client_sock, addr = ipv4_sock.accept()
                self.log_message(f"接受来自 {addr} 的连接")
                
                # 为每个连接创建新的IPv6 socket
                new_ipv6_sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
                new_ipv6_sock.connect((remote_ipv6, remote_port, 0, 0))
                
                # 创建双向转发线程
                thread1 = threading.Thread(target=self.tcp_bridge, args=(client_sock, new_ipv6_sock, "IPv4->IPv6"))
                thread2 = threading.Thread(target=self.tcp_bridge, args=(new_ipv6_sock, client_sock, "IPv6->IPv4"))
                
                thread1.daemon = True
                thread2.daemon = True
                
                thread1.start()
                thread2.start()
                
                # 保存socket以便后续关闭
                self.sockets.extend([client_sock, new_ipv6_sock])
                self.threads.extend([thread1, thread2])
                
        except Exception as e:
            if self.is_running:
                self.log_message(f"TCP错误: {str(e)}")
            
        self.log_message("TCP客户端转发器已停止")
        
    def tcp_forwarder_server(self, ipv4_sock, ipv6_sock, server_ipv6, server_port, game_port):
        """TCP服务端转发器 - 使用指定端口"""
        self.log_message(f"TCP服务端转发器已启动，监听端口 {server_port}")
        
        try:
            # 绑定IPv6 socket到服务端地址和指定端口
            ipv6_sock.bind((server_ipv6, server_port))
            ipv6_sock.listen(5)
            self.log_message(f"服务端监听在: [{server_ipv6}]:{server_port}")
            
            while self.is_running:
                try:
                    # 设置超时以便检查运行状态
                    ipv6_sock.settimeout(1.0)
                    
                    # 接受IPv6连接
                    remote_sock, remote_addr = ipv6_sock.accept()
                    self.log_message(f"接受来自 [{remote_addr[0]}]:{remote_addr[1]} 的连接")
                    
                    # 接受IPv4连接
                    # ipv4_sock.settimeout(1.0)
                    # client_sock, addr = ipv4_sock.accept()
                    # self.log_message(f"接受来自 {addr} 的连接")
                    # 创建新的IPv4 socket连接游戏服务器
                    try:
                        game_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                        game_sock.connect((self.local_ipv4_var.get(), game_port))
                        self.log_message(f"已连接到游戏服务器: {self.local_ipv4_var.get()}:{game_port}")
                    except Exception as e:
                        self.log_message(f"连接游戏服务器失败: {str(e)}")
                        remote_sock.close()
                        continue
                    
                    # 创建双向转发线程
                    # thread1 = threading.Thread(target=self.tcp_bridge, args=(client_sock, remote_sock, "IPv4->IPv6"))
                    # thread2 = threading.Thread(target=self.tcp_bridge, args=(remote_sock, client_sock, "IPv6->IPv4"))
                    thread1 = threading.Thread(target=self.tcp_bridge, args=(remote_sock, game_sock, "IPv6->IPv4"))
                    thread2 = threading.Thread(target=self.tcp_bridge, args=(game_sock, remote_sock, "IPv4->IPv6"))

                    thread1.daemon = True
                    thread2.daemon = True
                    
                    thread1.start()
                    thread2.start()
                    
                    # 保存socket和线程以便后续关闭
                    # self.sockets.extend([client_sock, remote_sock])
                    self.sockets.extend([game_sock, remote_sock])
                    self.threads.extend([thread1, thread2])
                    
                except socket.timeout:
                    continue
                except Exception as e:
                    if self.is_running:
                        self.log_message(f"TCP连接错误: {str(e)}")
                    continue
                    
        except Exception as e:
            if self.is_running:
                self.log_message(f"TCP服务端错误: {str(e)}")
            
        self.log_message("TCP服务端转发器已停止")
        
    def tcp_bridge(self, source, destination, direction):
        """TCP桥接功能"""
        try:
            while self.is_running:
                data = source.recv(4096)
                if not data:
                    break
                destination.sendall(data)
                # self.log_message(f"{direction}: 转发 {len(data)} 字节") # 频繁日志会刷掉重要信息，注释掉
        except:
            pass
        finally:
            try:
                source.close()
                destination.close()
            except:
                pass
            
    def on_closing(self):
        """程序关闭时的处理"""
        if self.is_running:
            if messagebox.askokcancel("退出", "转发正在运行，确定要退出吗？"):
                self.stop_forwarding()
                self.root.destroy()
        else:
            self.root.destroy()
    
    def save_config(self):
        """保存当前配置到文件"""
        if not self.config.has_section('config'):
            self.config.add_section('config')
        self.config.set('config', 'mode', self.mode_var.get())
        self.config.set('config', 'local_ipv4', self.local_ipv4_var.get())
        self.config.set('config', 'game_port', self.game_port_var.get())
        self.config.set('config', 'remote_ipv6', self.remote_ipv6_var.get())
        self.config.set('config', 'remote_port', self.remote_port_var.get())
        try:
            s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
            s.connect(("2400:3200::1", 80))  # ali IPv6 DNS
            ipv6 = s.getsockname()[0]
            s.close()
            if self.server_ipv6_var.get() == ipv6:
                self.config.set('config', 'server_ipv6', "")  # 如果是自动获取的地址，则不保存
            elif self.server_ipv6_var.get() == "::1":
                self.config.set('config', 'server_ipv6', "")  # 回环地址也不保存
            else:
                self.config.set('config', 'server_ipv6', self.server_ipv6_var.get())  # 保留用户输入的地址
        except:
            self.log_message("服务端ipv6地址保存失败")  # 无法获取IPv6地址时不做处理    
        # self.config.set('config', 'server_ipv6', self.server_ipv6_var.get())
        self.config.set('config', 'server_port', self.server_port_var.get())
        self.config.set('config', 'protocol', self.protocol_var.get())
        try:
            with open('_internal/config.ini', 'w', encoding='utf-8') as configfile:
                self.config.write(configfile)
            self.log_message("配置已保存")
        except Exception as e:
            self.log_message(f"保存配置失败: {str(e)}")
    
    def auto_get_ipv6(self):
        """尝试自动获取本机IPv6地址"""
        if self.mode_var.get() == "server":
            try:
                s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
                s.connect(("2400:3200::1", 80))  # ali IPv6 DNS
                ipv6 = s.getsockname()[0]
                self.server_ipv6_var.set(ipv6)
                self.log_message(f"自动获取IPv6地址: {ipv6}")
                s.close()
            except:
                self.server_ipv6_var.set("::1")  # 回环地址作为备选
                self.log_message("DNS解析失败,请检查是否支持ipv6,或尝试手动配置ipv6地址")
            
        else:
            messagebox.showinfo("信息", "仅在服务端模式下可用")
            return


def main():
    """主函数"""
    root = tk.Tk()
    app = IPv6toIPv4Forwarder(root)
    # 设置图标，保证图标丢失也可以运行
    # 打包到_internal下，更整洁(防止有人将图标当作程序启动，因此外部只留下exe)
    try:
        root.iconbitmap("icon.ico") # 打包后使用当前目录的图标,可以替换
    except:
        try:
            root.iconbitmap("_internal/icon.ico") # 默认图标
        except:
            pass
    # root.iconbitmap("icon.ico") 
    root.mainloop()

if __name__ == "__main__":
    main()